﻿#pragma once
#include <QJsonObject>
#include <QJsonArray>
#include <QVariantMap>
#include <QString>
#include <QDebug>

#include "opencv2/opencv.hpp"
#include "AsCoreGlobal.h"
#include "AsJsonTypeHandler.h"

#define DECLARE_JSON_VAR(_var) defField(&_var,#_var)
#define DECLARE_JSON_OBJECT(_obj) defSubObject(&_obj,#_obj)
#define DECLARE_SUB_STRUCTURE(_obj,_var) defSubField(&_obj,#_obj,&_obj._var,#_var)
#define encodeArray(_obj,_var) encodeJsonArray(_var,#_var,_obj)
#define decodeArray(_obj,_var) decodeJsonArray(_var,#_var,_obj)

class ASCORE_EXPORT AsJsonObject
{
	using Pair_Type_DataPtr = std::pair<QString, void*>;
	
	struct AsJsonObjectPrivate 
	{
		QMap<QString, Pair_Type_DataPtr> mapTypeData;
		QMap<QString, AsJsonObject*> mapChildObject;							//递归子类型
		QMap<QString, QMap<QString, Pair_Type_DataPtr>> mapSubStructure;		//子数据映射，实现非继承形式的递归结构	
	};

private:
	AsJsonObjectPrivate* m_pPrivate;

public:
	AsJsonObject();
	AsJsonObject(const AsJsonObject& other);
	AsJsonObject& operator=(const AsJsonObject& other);
	virtual ~AsJsonObject();

	virtual QJsonObject toJsonObject()const;

	virtual void fromJsonObject(const QJsonObject& json);

	virtual void onBuildStructure()const {};
public:
	QVariantMap toVariantMap()const;
	void fromVariantMap(const QVariantMap& vm);

protected:

	//注册子对象
	void defSubObject(AsJsonObject* pChild, QString childName)const;

	//重载const限定
	void defSubObject(const AsJsonObject* pChild, QString childName)const;

	//字段注册，通过字段注册的方式，可快速实现数据结构JSON化
	template<typename _TYPE>
	void defField(_TYPE* data, QString keyName) const
	{
		m_pPrivate->mapTypeData[keyName] = Pair_Type_DataPtr(typeid(_TYPE).name(), data);
	}

	//重载const限定
	template<typename _TYPE>
	void defField(const _TYPE* data, QString keyName) const
	{
		m_pPrivate->mapTypeData[keyName] = Pair_Type_DataPtr(typeid(_TYPE).name(), const_cast<_TYPE*>(data));
	}

	//注册子结构，可以在子对象不继承AsJsonObject的情况下，实现子结构包含效果
	template<typename _TYPE>
	void defSubField(void* pSub, QString subDataName, _TYPE* pSubData, QString fieldName)  const
	{
		auto subStructure = m_pPrivate->mapSubStructure[subDataName];
		subStructure[fieldName] = Pair_Type_DataPtr(typeid(_TYPE).name(), pSubData);
		m_pPrivate->mapSubStructure[subDataName] = subStructure;
	}

	//重载const限定
	template<typename _TYPE>
	void defSubField(const void* pSub, QString subDataName, const _TYPE* pSubData, QString fieldName)  const
	{
		auto subStructure = m_pPrivate->mapSubStructure[subDataName];
		subStructure[fieldName] = Pair_Type_DataPtr(typeid(_TYPE).name(), const_cast<_TYPE*>(pSubData));
		m_pPrivate->mapSubStructure[subDataName] = subStructure;
	}

private:
	void buildStructure()const;	
};

template<typename _JSONTYPE>
void encodeJsonArray(const QVector<_JSONTYPE>& v,QString key, QJsonObject& json) 
{
	if (!std::is_base_of<AsJsonObject, _JSONTYPE>())
	{
		qWarning() << typeid(_JSONTYPE).name() << " is not a child of AsJsonObject!";
		return;
	}

	QJsonArray jsArr;
	for (auto d : v)
		jsArr.append(d.toJsonObject());
	json[key] = jsArr;
}

template<typename _JSONTYPE>
void decodeJsonArray(QVector<_JSONTYPE>& v, QString key,const QJsonObject& json)
{
	if (!std::is_base_of<AsJsonObject, _JSONTYPE>())
	{
		qWarning() << typeid(_JSONTYPE).name() << " is not a child of AsJsonObject!";
		return;
	}
	v.clear();
	QJsonArray jsArr = json[key].toArray();
	for (auto item : jsArr)
	{
		_JSONTYPE d;
		d.fromJsonObject(item.toObject());
		v << d;
	}
}

namespace As {
	/**
	 * 外部接口，Json类型解析器注册模板
	 */
	template<typename _TYPE, typename _HANDLER>
	extern void registerTypeHandler()
	{
		if (std::is_base_of<AsJsonTypeHandler, _HANDLER>())
		{
			_HANDLER* pHandler = new _HANDLER();
			registerTypeHandlerImpl(typeid(_TYPE).name(), pHandler);
		}
		else {
			qWarning() << typeid(_HANDLER).name() << " is not a child of AsJsonTypeHandler!";
		}
	}

	/**
	 * Json类型解析器注册函数实现函数
	 */
	extern ASCORE_EXPORT void registerTypeHandlerImpl(QString typeId, AsJsonTypeHandler* pHandler);

	extern ASCORE_EXPORT AsJsonTypeHandler* getHandler(QString typeName);
}
